/**
 * @author zoulei
 * Python服务管理器
 * 负责Python服务的启动、关闭和生命周期管理
 */

import { spawn, ChildProcess } from 'child_process';
import axios from 'axios';
import path from 'path';
import { fileURLToPath } from 'url';
import net from 'net';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Python 服务配置
const PY_SERVICE_HOST = '127.0.0.1';
const PY_SERVICE_PORT = 5001;
const PY_SERVICE_URL = `http://${PY_SERVICE_HOST}:${PY_SERVICE_PORT}`;

export class PythonServiceManager {
  private pyProcess: ChildProcess | null = null;
  private pyExe!: string;
  private pyPath!: string;

  constructor() {
    // 构造函数不再初始化pyExe和pyPath，延迟到start方法
    this.pyProcess = null;
    // this.pyExe = ...
    // this.pyPath = ...
  }

  /**
   * 启动Python服务
   */
  async start(): Promise<void> {
    // 延迟初始化pyExe和pyPath，确保环境变量已加载
    this.pyExe = process.env.MCP_PYTHON_EXE || 'C:\\Users\\67480\\AppData\\Local\\Microsoft\\WindowsApps\\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\\python.exe';
    
    // 使用基于当前模块文件的绝对路径，避免依赖process.cwd()
    const currentDir = path.dirname(__filename);
    let projectRoot: string;
    console.error('当前环境:', process.env.NODE_ENV);
    if (process.env.NODE_ENV === 'development') {
      projectRoot = path.resolve(currentDir, '..');
    } else {
      projectRoot = currentDir;
    }
    this.pyPath = path.join(projectRoot, 'scripts/dm_service.py');
    console.error('脚本路径:', this.pyPath);
    
    if (this.pyProcess) return;

    // 启动前先检查端口占用情况
    console.error('正在检查端口占用情况...');
    const portInUse = await this.isPortInUse(PY_SERVICE_PORT);
    console.error(`端口检查结果: ${portInUse ? '被占用' : '可用'}`);
    
    if (portInUse) {
      console.error(`端口 ${PY_SERVICE_PORT} 被占用，尝试关闭已有的Python服务...`);
      // 启动前先尝试通过HTTP请求关闭已有的Python服务
      try {
        await axios.post(`${PY_SERVICE_URL}/shutdown`, {}, { timeout: 2000 });
        console.error('已发送关闭请求到Python服务');
        // 等待一下让服务完全关闭
        await new Promise(resolve => setTimeout(resolve, 2000));
        
        // 再次检查端口是否释放
        console.error('再次检查端口占用情况...');
        const stillInUse = await this.isPortInUse(PY_SERVICE_PORT);
        console.error(`二次端口检查结果: ${stillInUse ? '仍被占用' : '已释放'}`);
        if (stillInUse) {
          console.error(`警告: 端口 ${PY_SERVICE_PORT} 仍然被占用，可能被其他程序占用`);
        } else {
          console.error(`端口 ${PY_SERVICE_PORT} 已释放，可以启动新服务`);
        }
      } catch (e) {
        console.error('HTTP关闭请求失败，可能端口被其他程序占用:', e instanceof Error ? e.message : String(e));
      }
    } else {
      console.error(`端口 ${PY_SERVICE_PORT} 可用，直接启动新服务`);
    }

    try {
      this.pyProcess = spawn(this.pyExe, [this.pyPath], {
        stdio: ['ignore', 'pipe', 'pipe'],
        detached: false,
        env: {
          ...process.env,
          // 确保环境变量传递给子进程
          MCP_PYTHON_EXE: process.env.MCP_PYTHON_EXE,
          DM_HOST: process.env.DM_HOST,
          DM_USERNAME: process.env.DM_USERNAME,
          DM_PASSWORD: process.env.DM_PASSWORD,
          DM_HOME: process.env.DM_HOME
        }
      });
      // 捕获并转发 Python stderr 日志
      if (this.pyProcess.stderr) {
        this.pyProcess.stderr.on('data', (data) => {
          process.stderr.write(`[python] ${data}`);
        });
      }
    } catch (e) {
      // 启动子进程异常，返回 message 字段
      throw new Error('Python服务启动失败: ' + (e instanceof Error ? e.message : String(e)));
    }

    // 等待 Python 服务启动
    let started = false;
    for (let i = 0; i < 20; i++) {
      try {
        await axios.get(`${PY_SERVICE_URL}/ping`);
        started = true;
        break;
      } catch (e) {
        await new Promise(res => setTimeout(res, 300));
      }
    }
    if (!started) throw new Error('Python 服务启动失败');

    // 启动后主动同步配置
    const config = {
      host: process.env.DM_HOST || '<your_host>:<your_port>',
      username: process.env.DM_USERNAME || '<your_uid>',
      password: process.env.DM_PASSWORD || '<your_pwd>',
      home: process.env.DM_HOME || '<your_dm_home>'
    };

    console.error('=== 同步配置到Python服务 ===');
    console.error('配置信息:', JSON.stringify(config, null, 2));

    await axios.post(`${PY_SERVICE_URL}/config`, config);
    
    console.error('Python 数据服务已启动并同步配置');
  }

  /**
   * 检查端口是否被占用
   */
  private isPortInUse(port: number): Promise<boolean> {
    return new Promise((resolve) => {
      const socket = new net.Socket();
      let isDone = false;
      
      const onResult = (inUse: boolean) => {
        if (!isDone) {
          isDone = true;
          socket.destroy();
          resolve(inUse);
        }
      };
      
      // 设置超时
      const timeout = setTimeout(() => {
        onResult(true); // 超时认为端口被占用
      }, 1000);
      
      socket.on('connect', () => {
        clearTimeout(timeout);
        onResult(true); // 能连接成功，说明端口被占用
      });
      
      socket.on('error', (err: any) => {
        clearTimeout(timeout);
        if (err.code === 'ECONNREFUSED') {
          onResult(false); // 连接被拒绝，说明端口未被占用
        } else {
          console.error(`端口检查错误: ${err.message}`);
          onResult(true); // 其他错误认为端口被占用
        }
      });
      
      socket.on('timeout', () => {
        clearTimeout(timeout);
        onResult(true); // 超时认为端口被占用
      });
      
      socket.setTimeout(1000);
      socket.connect(port, '127.0.0.1');
    });
  }

  /**
   * 关闭Python服务
   */
  async stop(): Promise<void> {
    if (this.pyProcess) {
      console.error('正在关闭Python数据服务...');

      // 先检查端口是否被占用
      console.error('检查端口占用情况...');
      const portInUse = await this.isPortInUse(PY_SERVICE_PORT);
      console.error(`端口检查结果: ${portInUse ? '被占用' : '未被占用'}`);
      
      if (portInUse) {
        console.error(`端口 ${PY_SERVICE_PORT} 被占用，尝试通过HTTP请求关闭服务...`);
        // 只通过HTTP请求关闭
        try {
          await axios.post(`${PY_SERVICE_URL}/shutdown`, {}, { timeout: 2000 });
          console.error('已发送关闭请求到Python服务');
        } catch (e) {
          console.error('HTTP关闭请求失败:', e instanceof Error ? e.message : String(e));
        }
      } else {
        console.error(`端口 ${PY_SERVICE_PORT} 未被占用，Python服务可能已经关闭`);
      }

      // 清理进程引用
      this.pyProcess = null;
    }
  }

  /**
   * 获取服务URL
   */
  getServiceUrl(): string {
    return PY_SERVICE_URL;
  }

  /**
   * 检查服务是否运行
   */
  async isRunning(): Promise<boolean> {
    try {
      await axios.get(`${PY_SERVICE_URL}/ping`);
      return true;
    } catch (e) {
      return false;
    }
  }
}

// 创建全局实例
export const pythonServiceManager = new PythonServiceManager(); 